/*
* ==========================================模板类==========================================
* ===================================关联配件信息、仓库、日志数据块===================================
* 1. 增删改查
* ===================================关联配件信息、仓库、日志数据块===================================
* ==========================================模板类==========================================
*/

#ifndef __INFO_MANAGER_TEMPLATE_HPP__
#define __INFO_MANAGER_TEMPLATE_HPP__


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>
#include <fstream>


template<class T>
class InfoManagerTemplate
{
private:
    using IdFunction = int (T::*)() const;
    using StringFunction = std::string(T::*)() const;
    IdFunction getIdFunction;
    StringFunction getDepictFunction;

public:
    InfoManagerTemplate(IdFunction getId) :getIdFunction(getId) {}
    InfoManagerTemplate(IdFunction getId, StringFunction getString) :getIdFunction(getId), getDepictFunction(getString) {}
    ~InfoManagerTemplate() = default;

    int add_info(std::vector<std::shared_ptr<T>>& infoLib, const T& info);
    int delete_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id);
    int modify_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id, const T& info);
    int modify_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id, const std::string& description, const T& info);
    std::shared_ptr<T> find_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id);
    std::shared_ptr<T> find_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id, const std::string& description);
};


template<class T>
int InfoManagerTemplate<T>::add_info(std::vector<std::shared_ptr<T>>& infoLib, const T& info)
{
    infoLib.push_back(std::make_shared<T>(info));
    return 0;
}

template<class T>
int InfoManagerTemplate<T>::delete_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id)
{
    auto it = find_if(infoLib.begin(), infoLib.end(),
        [&id, this](const std::shared_ptr<T>& info) {return id == ((*info).*getIdFunction)();});//typename vector<T*>::iterator it

    if (it == infoLib.end())
        return -1;

    infoLib.erase(it);
    return 0;
}

template<class T>
int InfoManagerTemplate<T>::modify_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id, const T& info)
{
    auto it = std::find_if(infoLib.begin(), infoLib.end(), [&id, this](const std::shared_ptr<T>& info) {return id == ((*info).*getIdFunction)();});

    if (it == infoLib.end())
        return -1;

    std::shared_ptr<T> newObj = std::make_shared<T>(info); // 先创建新对象
    (*it) = newObj;
    return 0;
}

template<class T>
int InfoManagerTemplate<T>::modify_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id, const std::string& description, const T& info)
{
    auto it = std::find_if(infoLib.begin(), infoLib.end(),
        [&id, &description, this](const std::shared_ptr<T>& info) {return id == ((*info).*getIdFunction)() && description == ((*info).*getDepictFunction)(); });
    
    if (it == infoLib.end())
        return -1;
    std::shared_ptr<T> newInfo = std::make_shared<T>(info);
    (*it) = newInfo;
    return 0;
}

template<class T>
std::shared_ptr<T> InfoManagerTemplate<T>::find_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id)
{
    auto it = std::find_if(infoLib.begin(), infoLib.end(),
        [&id, this](const std::shared_ptr<T>& info) {return id == ((*info).*getIdFunction)();});

    if (it == infoLib.end())
        return nullptr;
    return (*it);
}

template<class T>
std::shared_ptr<T> InfoManagerTemplate<T>::find_info(std::vector<std::shared_ptr<T>>& infoLib, const int& id, const std::string& description)
{
    auto it = std::find_if(infoLib.begin(), infoLib.end(),
        [&id, &description, this](const std::shared_ptr<T>& info) {return id == ((*info).*getIdFunction)() && description == ((*info).*getDepictFunction)();});
    if (it == infoLib.end())
        return nullptr;
    return (*it);
}


/*====================================<序列化接口类模板>====================================*/

// template<class T>
// class SerializeTemplate
// {
// public:
//     std::string serialize(const T& obj);
//     T deSerialize(const std::string& str);

// };

// template<class T>
// std::string SerializeTemplate<T>::serialize(const T& obj)
// {
//     return obj.serialize();
// }

// template<class T>
// T SerializeTemplate<T>::deSerialize(const std::string& str)
// {
//     return obj.deSerialize(str);
// }

#endif